local Vector3 = CS.UnityEngine.Vector3

local align_helper = {}

local SetParent = function(tran, parent, b)
	if not tran then
		return;
	end

	if tran.parent == parent then
		return;
	end

	tran:SetParent(parent, b);
end

align_helper.EPivot = 
{
	middle = 0;
	middle_left = 1;
	middle_top = 2;
	middle_right = 3;
	middle_bottom = 4;
	left = 5; -- 相当于left_top
	left_top = 6;
	left_bottom = 7;
	right = 8; -- 相当于right_bottom
	right_top = 9;
	right_bottom = 10; 
}

local defaultIntervalX = 38;
local defaultIntervalY = 30;
local defaultPreRowCount = 25;
local defaultPivot = align_helper.EPivot.center;
local defaultAnimTimeLength = 0.1;

function align_helper:Focus(pokerTable, pivot, intervalX, preRowCount, startIndex, endIndex, maxIntervalX, minIntervalX, maxWidth, isAnim, animTimeLength)
	if pokerTable == nil or #pokerTable == 0 then
		return;
	end

	pivot = pivot or defaultPivot;
	intervalX = intervalX or defaultIntervalX;

	local offsetX = 0;
	local startX = 0;

	if pivot == align_helper.EPivot.middle then
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
		end
	elseif pivot == align_helper.EPivot.middle_left then
		startX = 0;
	elseif pivot == align_helper.EPivot.middle_top then
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
		end
	elseif pivot == align_helper.EPivot.middle_right then
		startX = 0;
		if #pokerTable > preRowCount then
			startX = 0 - math.floor(preRowCount-1) * intervalX;
		else
			startX = 0 - math.floor((#pokerTable-1)) * intervalX;
		end
	elseif pivot == align_helper.EPivot.middle_bottom then
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
		end
	end

	local x = 0;

	startIndex = startIndex or -1;
	endIndex = endIndex or -1;
	--超过范围不聚焦
	if startIndex <= 0 or endIndex <= 0 or startIndex > #pokerTable or endIndex > #pokerTable then
		for index, poker in pairs(pokerTable) do
			x = startX + ((index-1)%preRowCount) * intervalX;
			y = poker.position.y;
			local pos = Vector3(x, y, 0);
			if isAnim then
				animTimeLength = animTimeLength or defaultAnimTimeLength;
				poker:set_position(Vector3(poker.position.x, y, poker.position.z));
				poker.transform:DOLocalMoveX(x, animTimeLength);
			else
				poker:set_position(pos);
			end
		end
	else
		if startIndex > endIndex then
			startIndex, endIndex = endIndex, startIndex;
		end

		local focusCount = endIndex - startIndex + 1;

		local nofocusCount = #pokerTable - focusCount;

		--超过最大宽度，压缩聚焦宽度
		if focusCount * maxIntervalX + nofocusCount * minIntervalX > maxWidth then
			maxIntervalX = (maxWidth - nofocusCount * minIntervalX)/ focusCount;
		else
			minIntervalX = (maxWidth - focusCount * maxIntervalX)  / nofocusCount;
			--未聚焦的宽度不能超过最大
			if minIntervalX > maxIntervalX then
				minIntervalX = maxIntervalX;
			end
		end

		local lastX = startX;
		for index, poker in pairs(pokerTable) do
			if index > startIndex and index <= endIndex+1 then
				if index == 1 then
					x = startX;
				else
					x = lastX + maxIntervalX;
				end
				lastX = x;

				y = poker.position.y;	
			else
				if index == 1 then
					x = startX;
				else
					x = lastX + minIntervalX;
				end
				lastX = x;
				y = poker.position.y;	
			end
			local pos = Vector3(x, y, 0);
			
			if isAnim then
				animTimeLength = animTimeLength or defaultAnimTimeLength;
				poker:set_position(Vector3(poker.position.x, y, poker.position.z));
				poker.transform:DOLocalMoveX(x, animTimeLength);
			else
				poker:set_position(pos);
			end
		end
	end
end

--pivot:中心点
--intervalX:X轴间距
--intervalX:Y轴间距
--preRowCount:每一行限制个数，超过换行
--isAnim:排序的时候是否需要移动过程（移动动画）
--animTimeLength：动画时间
--focusStartIndex:聚焦起始点 （起始索引，结束索引 任意一下小于0则不聚焦）
--focusEndIndex:聚焦结束点（起始索引，结束索引 任意一下小于0则不聚焦）
--maxIntervalX:聚焦计算时最大间距（被聚焦的按最大计算）
--minIntervalX:聚焦计算时最小(未被聚焦的，至少为这个间距)
--maxWidth:聚焦计算时总宽度，如果超过，会压缩intervalX
function align_helper.Align(pokerTable, parent, pivot, intervalX, intervalY, preRowCount, isAnim, animTimeLength, focusStartIndex, focusEndIndex, maxIntervalX, minIntervalX, maxWidth)
	if pokerTable == nil or #pokerTable == 0 then
		return;
	end

	pivot = pivot or defaultPivot;
	intervalX = intervalX or defaultIntervalX;
	intervalY = intervalY or defaultIntervalY;
	preRowCount = preRowCount or defaultPreRowCount;

	local offsetX = 0;
	local offsetY = 0;
	local startX = 0;
	local startY = 0;

	if pivot == align_helper.EPivot.middle then
		offsetY = (math.ceil(#pokerTable/preRowCount) % 2 == 0) and (intervalY / 2) or 0;
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
			startY = offsetY + math.floor(((math.ceil(#pokerTable/preRowCount)-1)/2)) * intervalY;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
			startY = 0;
		end
		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.middle_left then
		startX = 0;
		if #pokerTable > preRowCount then
			offsetY = (math.ceil(#pokerTable/preRowCount) % 2 == 0) and (intervalY / 2) or 0;
			startY = offsetY + math.floor(((math.ceil(#pokerTable/preRowCount)-1)/2)) * intervalY;
		else
			startY = 0;
		end

		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.middle_top then
		startY = 0;
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
		end

		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.middle_right then
		startX = 0;
		if #pokerTable > preRowCount then
			startX = 0 - math.floor(preRowCount-1) * intervalX;

			offsetY = (math.ceil(#pokerTable/preRowCount) % 2 == 0) and (intervalY / 2) or 0;
			startY = offsetY + math.floor((math.ceil((#pokerTable/preRowCount)-1)/2)) * intervalY;
		else
			startY = 0;
			startX = 0 - math.floor((#pokerTable-1)) * intervalX;
		end

		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.middle_bottom then
		startY = 0;
		
		if #pokerTable > preRowCount then
			offsetX = (preRowCount%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((preRowCount-1)/2) * intervalX;
		else
			offsetX = (#pokerTable%2 == 0) and (-intervalX / 2) or 0;
			startX = offsetX - math.floor((#pokerTable-1)/2) * intervalX;
		end
	elseif pivot == align_helper.EPivot.left then
		startX = 0;
		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.left_top then
		startX = 0;
		startY = 0;
		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.left_bottom then
		startX = 0;
		if #pokerTable > preRowCount then
			startY = (math.ceil(#pokerTable / preRowCount)-1) * intervalY;
		else
			startY = 0;
		end
		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.right then
		startX = 0;
		if #pokerTable > preRowCount then
			startX = 0 - math.floor(preRowCount-1) * intervalX;
		else
			startX = 0 - math.floor((#pokerTable-1)) * intervalX;
		end

		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.right_top then
		startX = 0;
		if #pokerTable > preRowCount then
			startX = 0 - math.floor(preRowCount-1) * intervalX;
		else
			startX = 0 - math.floor((#pokerTable-1)) * intervalX;
		end

		intervalY = -intervalY;
	elseif pivot == align_helper.EPivot.right_bottom then
		if #pokerTable > preRowCount then
			startX = 0 - math.floor(preRowCount-1) * intervalX;
			startY = (math.ceil(#pokerTable / preRowCount)-1) * intervalY;
		else
			startX = 0 - math.floor((#pokerTable-1)) * intervalX;
			startY = 0;
		end

		intervalY = -intervalY;		
	end

	local x = 0;
	local y = 0;

	focusStartIndex = focusStartIndex or -1;
	focusEndIndex = focusEndIndex or -1;
	--超过范围不聚焦
	if focusStartIndex <= 0 or focusEndIndex <= 0 or focusStartIndex > #pokerTable or focusEndIndex > #pokerTable then
		for index, poker in pairs(pokerTable) do
			poker:set_parent(parent);
			x = startX + ((index-1)%preRowCount) * intervalX;
			y = startY + (math.ceil(index/preRowCount)-1) * intervalY
			if poker.unselect then
				poker:unselect();	
			end
			local pos = Vector3(x, y, 0);
			if isAnim then
				animTimeLength = animTimeLength or defaultAnimTimeLength;
				poker:set_position(Vector3(poker.position.x, y, poker.position.z));
				poker.transform:DOLocalMoveX(x, animTimeLength);
			else
				poker:set_position(pos);
			end
			
			poker:set_aslastsibling();	
		end
	else
		if focusStartIndex > focusEndIndex then
			focusStartIndex, focusEndIndex = focusEndIndex, focusStartIndex;
		end

		local focusCount = focusEndIndex - focusStartIndex + 1;

		local nofocusCount = #pokerTable - focusCount;

		--超过最大宽度，压缩聚焦宽度
		if focusCount * maxIntervalX + nofocusCount * minIntervalX > maxWidth then
			maxIntervalX = (maxWidth - nofocusCount * minIntervalX)/ focusCount;
		else
			minIntervalX = (maxWidth - focusCount * maxIntervalX)  / nofocusCount;
			--未聚焦的宽度不能超过最大
			if minIntervalX > maxIntervalX then
				minIntervalX = maxIntervalX;
			end
		end

		local lastX = startX;
		for index, poker in pairs(pokerTable) do
			poker:set_parent(parent);
			if index > focusStartIndex and index <= focusEndIndex + 1 then
				if index == 1 then
					x = startX;
				else
					x = lastX + maxIntervalX;
				end
				lastX = x;

				y = startY + (math.ceil(index/preRowCount)-1) * intervalY	
			else
				if index == 1 then
					x = startX;
				else
					x = lastX + minIntervalX;
				end
				lastX = x;
				y = startY + (math.ceil(index/preRowCount)-1) * intervalY	
			end

			if poker.unselect then
				poker:unselect();	
			end
			local pos = Vector3(x, y, 0);
			
			if isAnim then
				animTimeLength = animTimeLength or defaultAnimTimeLength;
				poker:set_position(Vector3(poker.position.x, y, poker.position.z));
				poker.transform:DOLocalMoveX(x, animTimeLength);
			else
				poker:set_position(pos);
			end
			
			poker:set_aslastsibling();
		end
	end
end


local Sin = CS.UnityEngine.Mathf.Sin
local Cos = CS.UnityEngine.Mathf.Cos
function align_helper.Sector_Align(pokerTable, parent, angle, radius, anim, anim_time)
	angle = angle or 5
	radius = radius or 1
	anim_time = anim_time or 0.3

	local poker_angles = {}

	local start_angle = 0
	if #pokerTable %2 ~= 0 then
		start_angle = math.floor(#pokerTable/2) * angle
	else
		start_angle = (#pokerTable/2 - 1) * angle + angle*0.5
	end

	for i = 1, #pokerTable do
		local a = Vector3(0, 0, start_angle - (i-1) *  angle)
		if anim then
			pokerTable[i].transform:DOLocalRotate(a, anim_time)
		else
			pokerTable[i].transform.localEulerAngles = a
		end
		table.insert(poker_angles, a)
	end

	for index, poker in ipairs(pokerTable) do
		local a = poker_angles[index]
		ang = CS.UnityEngine.Mathf.Deg2Rad * a.z;
		local x = 0 - radius * Sin(ang)
		local y = 0 + radius * Cos(ang)
		local z = 0

		poker:set_parent(parent, false)
		local pos = Vector3(x, y, z)
		if anim then
			poker.transform:DOLocalMove(pos, anim_time)
		else
			poker.transform.localPosition = pos
		end
		
	end
end

return align_helper

